package com.zjj.disk.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjj.disk.config.ImportValidationException;
import com.zjj.disk.controller.result.Result;
import com.zjj.disk.mapper.BookKeepingMapper;
import com.zjj.disk.pojo.BookKeeping;
import com.zjj.disk.pojo.BookKeepingDTO;
import com.zjj.disk.pojo.Dictionary;
import com.zjj.disk.pojo.TransactionType;
import com.zjj.disk.service.BookKeepingService;
import com.zjj.disk.utils.DateUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class BookKeepingServiceImpl extends ServiceImpl<BookKeepingMapper, BookKeeping> implements BookKeepingService {

    @Autowired
    private BookKeepingMapper bookKeepingMapper;

    /**
     * 根据条件分页查询记账记录
     *
     * @param queryDto    查询条件
     * @param currentPage 当前页码
     * @param pageSize    每页大小
     * @return 分页结果
     */
    public IPage<BookKeepingDTO> getBookKeepingByConditions(BookKeepingDTO queryDto, int currentPage, int pageSize) {
        // 创建分页对象
        Page<BookKeeping> page = new Page<>(currentPage, pageSize);

        // 构建查询条件
        QueryWrapper<BookKeeping> queryWrapper = buildQueryWrapper(queryDto);

        // 执行分页查询
        IPage<BookKeeping> bookKeepingPage = bookKeepingMapper.selectPage(page, queryWrapper);

        // 格式化时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        // 将查询结果转换为 DTO 列表
        List<BookKeepingDTO> bookKeepingDTOList = bookKeepingPage.getRecords().stream()
                .map(bookKeeping -> {
                    BookKeepingDTO dto = new BookKeepingDTO();
                    BeanUtils.copyProperties(bookKeeping, dto);
                    dto.setTime(dateFormat.format(bookKeeping.getTime()));
                    dto.setCreatedAt(dateFormat.format(bookKeeping.getCreatedAt()));
                    return dto;
                })
                .collect(Collectors.toList());

        // 创建分页结果对象
        Page<BookKeepingDTO> resultPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        resultPage.setRecords(bookKeepingDTOList);

        return resultPage;
    }

    /**
     * 构建查询条件
     *
     * @param queryDto 查询条件
     * @return 查询条件包装器
     */
    private QueryWrapper<BookKeeping> buildQueryWrapper(BookKeepingDTO queryDto) {
        QueryWrapper<BookKeeping> queryWrapper = new QueryWrapper<>();

        // 动态构建查询条件
        if (queryDto.getProject() != null && !queryDto.getProject().isEmpty()) {
            queryWrapper.like("project", queryDto.getProject());
        }
        if (queryDto.getType() != null && !queryDto.getType().isEmpty()) {
            queryWrapper.like("type", queryDto.getType());
        }
        if (queryDto.getTime() != null && !queryDto.getTime().isEmpty()) {
            queryWrapper.eq("time", queryDto.getTime());
        }
        if (queryDto.getRemark() != null && !queryDto.getRemark().isEmpty()) {
            queryWrapper.like("remark", queryDto.getRemark());
        }
        if (queryDto.getCreatedAt() != null && !queryDto.getCreatedAt().isEmpty()) {
            queryWrapper.eq("created_at", queryDto.getCreatedAt());
        }
        if (queryDto.getAmount() != null) {
            queryWrapper.like("amount", queryDto.getAmount());
        }
        if (queryDto.getUserName() != null && !queryDto.getUserName().isEmpty()) {
            queryWrapper.like("user_name", queryDto.getUserName());
        }
        queryWrapper.orderByDesc("last_modified_at");
        return queryWrapper;
    }

    /**
     * 新增记账记录
     *
     * @param bookKeepingDTO 记账记录 DTO
     * @return 是否成功
     */
    public boolean addBookKeeping(BookKeepingDTO bookKeepingDTO) {
        // 创建实体对象
        BookKeeping bookKeeping = new BookKeeping();
        try {
            // 将 DTO 属性复制到实体对象
            BeanUtils.copyProperties(bookKeepingDTO, bookKeeping);
            bookKeeping.setTime(DateUtils.convertStringToDate(bookKeepingDTO.getTime()));
        } catch (Exception e) {
            throw new IllegalArgumentException("记账信息新增失败");
        }
        // 保存到数据库
        return save(bookKeeping);
    }


    /**
     * @return 获取本年度最高金额 amount
     */
    public BookKeeping getMaxAmountForCurrentYear() {
        LocalDate now = LocalDate.now();
        Date startOfYear = Date.from(now.withDayOfYear(1).atStartOfDay(ZoneId.of("UTC")).toInstant());
        Date endOfYear = Date.from(now.withDayOfYear(now.lengthOfYear()).atStartOfDay(ZoneId.of("UTC")).toInstant());

        QueryWrapper<BookKeeping> queryWrapper = Wrappers.query();
        queryWrapper.ge("time", startOfYear)
                .le("time", endOfYear)
                .orderByDesc("amount")
                .last("limit 1");

        BookKeeping bookKeeping = bookKeepingMapper.selectOne(queryWrapper);
        return bookKeeping;
    }

    /**
     * @return 获取历史最高金额 amount
     */
    public BookKeeping getMaxAmountHistorical() {
        QueryWrapper<BookKeeping> queryWrapper = Wrappers.query();
        queryWrapper.orderByDesc("amount")
                .last("limit 1");

        BookKeeping bookKeeping = bookKeepingMapper.selectOne(queryWrapper);
        return bookKeeping;
    }

    /**
     * @return 获取 project='支出'/'收入' 的最高金额 amount
     */
    public BookKeeping getMaxAmountForExpense(String projectName) {
        QueryWrapper<BookKeeping> queryWrapper = Wrappers.query();
        queryWrapper.eq("project", projectName)
                .orderByDesc("amount")
                .last("limit 1");

        BookKeeping bookKeeping = bookKeepingMapper.selectOne(queryWrapper);
        return bookKeeping;
    }

    /**
     * @return 获取明细
     */
    public Result detailedBooks() {
        JSONObject json = new JSONObject();
        try {
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
            formatter.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 使用中国时区
            LocalDate now = LocalDate.now();

            // 计算日期
            Date startOfYear = Date.from(now.withDayOfYear(1).atStartOfDay(ZoneId.of("UTC")).toInstant());
            Date endOfYear = Date.from(now.withDayOfYear(now.lengthOfYear()).atStartOfDay(ZoneId.of("UTC")).toInstant());
            LocalDate startOfMonth = now.withDayOfMonth(1);
            LocalDate endOfMonth = now.withDayOfMonth(now.lengthOfMonth());
            Date startOfMonthDate = Date.from(startOfMonth.atStartOfDay(ZoneId.of("UTC")).toInstant());
            Date endOfMonthDate = Date.from(endOfMonth.atStartOfDay(ZoneId.of("UTC")).toInstant());

            // 调用各个查询方法
            BookKeeping maxAmountCurrentYear = bookKeepingMapper.getMaxAmountCurrentYear(startOfYear, endOfYear);
            if (maxAmountCurrentYear != null) {
                String formattedTime = formatter.format(maxAmountCurrentYear.getTime());
                String max = "本年度最高" + TransactionType.getNameByCode(maxAmountCurrentYear.getType()) + "为：" + maxAmountCurrentYear.getAmount() + "，项目为：" + maxAmountCurrentYear.getProject() + "，时间是" + formattedTime;
                json.put("maxAmountForCurrentYear", max);
                json.put("maxAmountForCurrentYearName", maxAmountCurrentYear.getUserName());
            }

            BookKeeping maxAmountHistorical = bookKeepingMapper.getMaxAmountHistorical();
            if (maxAmountHistorical != null) {
                String formattedTime = formatter.format(maxAmountHistorical.getTime());
                String hName = "历史最高" + TransactionType.getNameByCode(maxAmountHistorical.getType()) + "为：" + maxAmountHistorical.getAmount() + "，项目为：" + maxAmountHistorical.getProject() + "，时间是" + formattedTime;
                json.put("maxAmountHistorical", hName);
                json.put("maxAmountHistoricalName", maxAmountHistorical.getUserName());
            }

            BookKeeping maxAmountExpense = bookKeepingMapper.getMaxAmountExpense();
            if (maxAmountExpense != null) {
                String formattedTime = formatter.format(maxAmountExpense.getTime());
                String expenseName = "支出最高为：" + maxAmountExpense.getAmount() + "，项目为：" + maxAmountExpense.getProject() + "，时间是" + formattedTime;
                json.put("maxAmountExpense", expenseName);
                json.put("maxAmountExpenseName", maxAmountExpense.getUserName());
            }

            BookKeeping maxAmountIncome = bookKeepingMapper.getMaxAmountIncome();
            if (maxAmountIncome != null) {
                String formattedTime = formatter.format(maxAmountIncome.getTime());
                String incomeName = "收入最高为：" + maxAmountIncome.getAmount() + "，项目为：" + maxAmountIncome.getProject() + "，时间是" + formattedTime;
                json.put("maxAmountIncome", incomeName);
                json.put("maxAmountIncomeName", maxAmountIncome.getUserName());
            }

            BigDecimal totalIncomeCurrentMonth = bookKeepingMapper.getTotalIncomeCurrentMonth(startOfMonthDate, endOfMonthDate);
            json.put("totalIncomeForCurrentMonth", totalIncomeCurrentMonth.toPlainString());

            BigDecimal totalExpenseCurrentMonth = bookKeepingMapper.getTotalExpenseCurrentMonth(startOfMonthDate, endOfMonthDate);
            json.put("totalExpenseForCurrentMonth", totalExpenseCurrentMonth.toPlainString());

            // 计算当月结余
            BigDecimal balance = totalIncomeCurrentMonth.subtract(totalExpenseCurrentMonth);
            json.put("balanceForCurrentMonth", balance.toPlainString());

        } catch (Exception e) {
            e.printStackTrace();
            return new Result().error("查询失败" + e.getMessage());
        }
        return new Result().success().addData("success", json);
    }

    /**
     * 获取当前月的总收入、总支出及各项目的盈亏情况
     *
     * @return 用户名称 包含总收入、总支出及各项目盈亏情况的Map
     */
    public Map<String, Object> getCurrentMonthSummary(String userName, String yearMonth) {
        yearMonth = yearMonth+"-01";
        // 解析传入的年月字符串
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate date = LocalDate.parse(yearMonth, formatter);

        // 计算指定月的起始时间和结束时间
        LocalDateTime startOfMonth = date.withDayOfMonth(1).atStartOfDay();
        LocalDateTime endOfMonth = date.withDayOfMonth(date.lengthOfMonth()).atTime(23, 59, 59);

        // 构建查询条件，筛选指定月的数据
        QueryWrapper<BookKeeping> queryWrapper = new QueryWrapper<>();
        queryWrapper.between("time", startOfMonth, endOfMonth);
        queryWrapper.eq("user_name", userName);

        // 执行查询，获取指定月的所有账目记录
        List<BookKeeping> bookKeepings = bookKeepingMapper.selectList(queryWrapper);

        // 初始化变量
        BigDecimal totalIncome = BigDecimal.ZERO;
        BigDecimal totalExpense = BigDecimal.ZERO;
        Map<String, BigDecimal> projectBalances = new HashMap<>();

        // 遍历账目记录，计算总收入、总支出及各项目的盈亏
        for (BookKeeping bookKeeping : bookKeepings) {
            BigDecimal amount = new BigDecimal(String.valueOf(bookKeeping.getAmount()));
            if ("income".equals(bookKeeping.getType())) {
                totalIncome = totalIncome.add(amount);
                projectBalances.merge(bookKeeping.getProject(), amount, BigDecimal::add);
            } else if ("expenditure".equals(bookKeeping.getType())) {
                totalExpense = totalExpense.add(amount);
                projectBalances.merge(bookKeeping.getProject(), amount.negate(), BigDecimal::add);
            }
        }

        // 计算当月的总收入和总支出的差额
        BigDecimal balanceAmount = totalIncome.subtract(totalExpense);
        String balanceType = balanceAmount.compareTo(BigDecimal.ZERO) > 0 ? "收入大于支出" : "支出大于收入";

        // 按金额倒序排序
        List<Map.Entry<String, BigDecimal>> sortedEntries = new ArrayList<>(projectBalances.entrySet());
        sortedEntries.sort(Map.Entry.<String, BigDecimal>comparingByValue().reversed());

        // 将排序后的结果转换回Map
        Map<String, BigDecimal> sortedProjectBalances = new LinkedHashMap<>();
        for (Map.Entry<String, BigDecimal> entry : sortedEntries) {
            sortedProjectBalances.put(entry.getKey(), entry.getValue());
        }

        // 将结果封装到Map中返回
        Map<String, Object> result = new HashMap<>();
        result.put("userName", userName); // 添加用户名称
        result.put("totalIncome", totalIncome); // 当月收入
        result.put("totalExpense", totalExpense); // 当月支出
        result.put("projectBalances", sortedProjectBalances); // 当月的收支项目
        result.put("balanceType", balanceType); // 添加当月的收支情况
        result.put("balanceAmount", balanceAmount); // 添加当月的净收入或净支出金额

        return result;
    }


    @Autowired
    private DictionaryServiceImpl identityService;

    public List<BookKeeping> importFromExcel(MultipartFile file) {
        // 验证文件类型
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("文件不能为空");
        }
        String contentType = file.getContentType();
        if (!"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet".equals(contentType)) {
            throw new IllegalArgumentException("只支持 .xlsx 格式的文件");
        }

        List<BookKeeping> bookKeepings = new ArrayList<>();
        try (InputStream inputStream = file.getInputStream();
             Workbook workbook = new XSSFWorkbook(inputStream)) {
            List<Dictionary> byParentCode = identityService.getByParentCode("user_info");
            List<String> nameList = byParentCode.stream().distinct().map(Dictionary::getName).collect(Collectors.toList());

            Sheet sheet = workbook.getSheetAt(0);
            DataFormatter dataFormatter = new DataFormatter();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

            for (Row row : sheet) {
                if (row.getRowNum() == 0) continue; // 跳过表头

                BookKeeping bookKeeping = new BookKeeping();
                String project = dataFormatter.formatCellValue(row.getCell(0)).trim();
                String type = dataFormatter.formatCellValue(row.getCell(1)).trim();
                String timeStr = dataFormatter.formatCellValue(row.getCell(2)).trim();
                String amountStr = dataFormatter.formatCellValue(row.getCell(3)).trim();
                String userName = dataFormatter.formatCellValue(row.getCell(4)).trim();
                String remark = dataFormatter.formatCellValue(row.getCell(5)).trim();

                // 验证项目名称
                if (project.isEmpty()) {
                    throw new ImportValidationException("项目名称不能为空，行号: " + (row.getRowNum() + 1));
                }

                // 验证类型
                if (type.isEmpty()) {
                    throw new ImportValidationException("类型不能为空，行号: " + (row.getRowNum() + 1));
                }
                if (StringUtils.isBlank(TransactionType.getCodeByName(type))) {
                    throw new ImportValidationException("请填写正确的类型，行号: " + (row.getRowNum() + 1));
                }

                // 验证时间
                if (timeStr.isEmpty()) {
                    throw new ImportValidationException("时间不能为空，行号: " + (row.getRowNum() + 1));
                }
                try {
                    bookKeeping.setTime(dateFormat.parse(timeStr));
                } catch (ParseException e) {
                    throw new ImportValidationException("时间格式不正确，行号: " + (row.getRowNum() + 1), e);
                }

                // 验证用户名
                if (userName.isEmpty()) {
                    throw new ImportValidationException("用户名不能为空，行号: " + (row.getRowNum() + 1));
                }

                if (!nameList.contains(userName)) {
                    throw new ImportValidationException("用户不是系统用户，请重新修改，行号: " + (row.getRowNum() + 1));
                }

                // 验证金额
                if (amountStr.isEmpty()) {
                    throw new ImportValidationException("金额不能为空，行号: " + (row.getRowNum() + 1));
                }
                if (!NumberUtils.isCreatable(amountStr)) {
                    throw new ImportValidationException("金额格式不正确，行号: " + (row.getRowNum() + 1));
                }
                BigDecimal amount = new BigDecimal(amountStr);

                // 设置属性
                bookKeeping.setProject(project);
                bookKeeping.setType(type);
                bookKeeping.setRemark(remark);
                bookKeeping.setUserName(userName);
                bookKeeping.setAmount(amount);

                bookKeepings.add(bookKeeping);
            }

            // 保存到数据库
            saveBatch(bookKeepings);

        } catch (ImportValidationException e) {
            log.error("导入文件时发生验证错误:", e);
            throw e;
        } catch (Exception e) {
            log.error("导入文件时发生未知错误", e);
            throw new RuntimeException("导入文件时发生错误", e);
        }
        return bookKeepings;
    }


    @Override
    public int deleteByIds(List<Integer> ids) {
        return removeByIds(ids) ? ids.size() : 0;
    }

}
